﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using myTXTReader.Properties;

namespace myTXTReader
{
    public partial class Form1 : Form
    {
        FileInfo file;
        StreamReader sr;
        ArrayList documents;
        OpenFileDialog ofd;
        private Font mainFont;          // font used to display all lines
        private Font emptyDocumentFont; // font used to display empty message
        private Brush mainBrush = Brushes.Blue;
        private Brush emptyDocumentBrush = Brushes.Red;
        private int lineHeight;        // height in pixels of one line
        private int margin = 3;
        int startLine = 0;//绘图开始行号
        int endLine = 0;//绘图结束行号
        int inStartLine = 0;//开始行号.小行号
        int inEndLine = 0;//结束行号.小行号
        ArrayList docInLines;
        const string AppName = "myBooker";

        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 加载文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ofd_FileOk(object sender, CancelEventArgs e)
        {
            file = new FileInfo(ofd.FileName);
            LoadBook();
        }

        private void LoadBook()
        {
            documents = new ArrayList();
            string readline = "";
            sr = new StreamReader(file.FullName, Encoding.GetEncoding("gb2312"));
            while ((readline = sr.ReadLine()) != null)
            {
                //自动形成段落缩进
                if (Settings.Default.SetAutoClip)
                    readline = "　　" + readline.TrimStart();
                //如果设置的为空行跳过就不读
                if (readline.Trim() != "" || Settings.Default.SetSkipBlank)
                    documents.Add(readline);
            }
            sr.Close();
            SetLastBook();
            //this.Text = string.Format(AppName + " - 读：【{0}】", GetBookName());
            statProgress.Maximum = documents.Count;
            statProgress.Value = 0;
            ShowInfo();
            this.Invalidate();
        }

        private void SetLastBook()
        {
            if (Settings.Default.LastFile1 != file.FullName &&
                Settings.Default.LastFile2 != file.FullName &&
                Settings.Default.LastFile3 != file.FullName &&
                Settings.Default.LastFile4 != file.FullName &&
                Settings.Default.LastFile5 != file.FullName)
            {
                Settings.Default.LastFile5 = Settings.Default.LastFile4;
                Settings.Default.LastFile4 = Settings.Default.LastFile3;
                Settings.Default.LastFile3 = Settings.Default.LastFile2;
                Settings.Default.LastFile2 = Settings.Default.LastFile1;
            }
            else
            {
                if (Settings.Default.LastFile5 == file.FullName)
                {
                    Settings.Default.LastFile5 = Settings.Default.LastFile4;
                    Settings.Default.LastFile4 = Settings.Default.LastFile3;
                    Settings.Default.LastFile3 = Settings.Default.LastFile2;
                    Settings.Default.LastFile2 = Settings.Default.LastFile1;
                }
                else if (Settings.Default.LastFile4 == file.FullName)
                {
                    Settings.Default.LastFile4 = Settings.Default.LastFile3;
                    Settings.Default.LastFile3 = Settings.Default.LastFile2;
                    Settings.Default.LastFile2 = Settings.Default.LastFile1;
                }
                else if (Settings.Default.LastFile3 == file.FullName)
                {
                    Settings.Default.LastFile3 = Settings.Default.LastFile2;
                    Settings.Default.LastFile2 = Settings.Default.LastFile1;
                }
                else if (Settings.Default.LastFile2 == file.FullName)
                {
                    Settings.Default.LastFile2 = Settings.Default.LastFile1;
                }
            }
            Settings.Default.LastFile1 = file.FullName;
            Settings.Default.Save();
            SetLastBookMenu();
        }

        private void SetLastBookMenu()
        {
            mnuFileHistory.DropDownItems.Clear();
            FileInfo ff;
            ToolStripMenuItem tsmi = new ToolStripMenuItem();
            if (Settings.Default.LastFile1 != "")
            {
                tsmi = new ToolStripMenuItem();
                ff = new FileInfo(Settings.Default.LastFile1);
                tsmi.Text = ff.Name;
                tsmi.Tag = ff;
                tsmi.Checked = true;
                tsmi.Click += new EventHandler(tsmi_Click);
                mnuFileHistory.DropDownItems.Add(tsmi);
            }
            if (Settings.Default.LastFile2 != "")
            {
                tsmi = new ToolStripMenuItem();
                ff = new FileInfo(Settings.Default.LastFile2);
                tsmi.Text = ff.Name;
                tsmi.Tag = ff;
                tsmi.Click += new EventHandler(tsmi_Click);
                mnuFileHistory.DropDownItems.Add(tsmi);
            }
            if (Settings.Default.LastFile3 != "")
            {
                tsmi = new ToolStripMenuItem();
                ff = new FileInfo(Settings.Default.LastFile3);
                tsmi.Text = ff.Name;
                tsmi.Tag = ff;
                tsmi.Click += new EventHandler(tsmi_Click);
                mnuFileHistory.DropDownItems.Add(tsmi);
            }
            if (Settings.Default.LastFile4 != "")
            {
                tsmi = new ToolStripMenuItem();
                ff = new FileInfo(Settings.Default.LastFile4);
                tsmi.Text = ff.Name;
                tsmi.Tag = ff;
                tsmi.Click += new EventHandler(tsmi_Click);
                mnuFileHistory.DropDownItems.Add(tsmi);
            }
            if (Settings.Default.LastFile5 != "")
            {
                tsmi = new ToolStripMenuItem();
                ff = new FileInfo(Settings.Default.LastFile5);
                tsmi.Text = ff.Name;
                tsmi.Tag = ff;
                tsmi.Click += new EventHandler(tsmi_Click);
                mnuFileHistory.DropDownItems.Add(tsmi);
            }

            
        }

        void tsmi_Click(object sender, EventArgs e)
        {
            file = (FileInfo)((ToolStripMenuItem)sender).Tag;
            LoadBook();
        }

        private void ShowInfo()
        {
            string infos = "";
            if (file == null)
            {
                infos = "当前无加载内容";
            }
            else
            {
                infos = string.Format("书本【{0}】，共有 {1} 行，当前第 {2}.{4}-{3}.{5} 行，阅读进度{6}%",
                    GetBookName(),
                    documents.Count,
                    startLine,
                    endLine,
                    inStartLine,
                    inEndLine,
                    Convert.ToInt32((startLine / documents.Count) * 100));
            }
            statInfo.Text = infos;
            this.Text = AppName + " - " + infos;
            statProgress.Value = startLine;
            Settings.Default.LastLine1 = startLine;
            Settings.Default.LastLine2 = inStartLine;
            Settings.Default.Save();
        }
        private string GetBookName()
        {
            return file.Name.Substring(0, file.Name.LastIndexOf('.'));
        }


        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Settings.Default.SetSkipBlank = mnuSettingsSkipBlankLine.Checked;
            //Settings.Default.SetAutoClip = mnuSettingAutoClip.Checked;
            Settings.Default.FormSize = this.Size;
            Settings.Default.Save();
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化
            ofd = new OpenFileDialog();
            ofd.Filter = "TXT文件(*.txt)|*.txt";
            ofd.FileOk += new CancelEventHandler(ofd_FileOk);
            documents = new ArrayList();
            mainFont = new Font("Arial", 10);
            lineHeight = mainFont.Height;
            emptyDocumentFont = new Font("Verdana", 13, FontStyle.Bold);
            SetLastBookMenu();
            statTime.Text = DateTime.Now.ToString("HH:mm:ss");
            Init();
        }

        public void Init()
        {
            if (Settings.Default.Font != null)
                mainFont = Settings.Default.Font;
            else
                mainFont = new Font("Arial", 10);
            this.BackColor = Settings.Default.BackgroundColor;
            if (Settings.Default.FontColor != null)
                mainBrush = new SolidBrush(Settings.Default.FontColor);
            else
                mainBrush = Brushes.Black;
            margin = Settings.Default.TextLineMargin;


        }

        /// <summary>
        /// 菜单：文件-打开
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuFileOpen_Click(object sender, EventArgs e)
        {
            ofd.ShowDialog();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics dc = e.Graphics;
            //dc.Clear(Settings.Default.BackgroundColor);
            if (documents.Count == 0)
            {
                dc.DrawString("未打开书本", emptyDocumentFont,
                    emptyDocumentBrush, new Point(e.ClipRectangle.Left, e.ClipRectangle.Top));
                return;
            }
            bool isFull = false;
            int curIndex = startLine;
            int inCurIndex = inStartLine;
            PointF printPoint = e.ClipRectangle.Location;
            while (!isFull)
            {
                string aa = documents[curIndex].ToString();
                docInLines = FormatStringToPrint(dc, aa, e.ClipRectangle.Width, mainFont);
                for (int i = inCurIndex; i < docInLines.Count; i++)
                {
                    SizeF ss = dc.MeasureString(docInLines[i].ToString(), mainFont);
                    printPoint.Y += margin;
                    if (printPoint.Y + ss.Height > e.ClipRectangle.Height + e.ClipRectangle.Top)
                    {
                        //超出了
                        isFull = true;
                        endLine = curIndex;
                        inEndLine = i;
                        break;
                    }
                    else
                    {
                        dc.DrawString(docInLines[i].ToString(), mainFont, mainBrush, printPoint);
                        printPoint.Y += margin + ss.Height;
                    }
                    inEndLine = 0;
                }
                if (inEndLine == docInLines.Count)
                    inEndLine = 0;
                curIndex++;
                inCurIndex = 0;
                if (curIndex >= documents.Count)
                    break;
            }
            ShowInfo();
        }

        private ArrayList FormatStringToPrint(Graphics g, string intext, int width, Font font)
        {
            ArrayList rtn = new ArrayList();
            if (g.MeasureString(intext, font).Width <= width)
                rtn.Add(intext);
            else
            {
                int testLen = Convert.ToInt32(width / g.MeasureString("国", font).Width);
                bool isfit = true;
                string temp = "";
                int i = 0;
                float cFlag, bFlag;
                cFlag = bFlag = 0;
                int curLen = testLen;
                while (isfit)
                {
                    if (curLen > intext.Length)
                        curLen = intext.Length;
                    temp = intext.Substring(0, curLen);
                    cFlag = g.MeasureString(temp, font).Width - width;
                    if (cFlag == 0
                        || (bFlag > 0 && cFlag < 0)
                        || (cFlag > 0 && bFlag < 0)
                        || (cFlag < 0 && curLen == intext.Length))//这类都是说明这个时候的宽度就是Ok的
                    {
                        if (bFlag < 0 && cFlag > 0)
                            curLen--;
                        temp = intext.Substring(0, curLen);
                        rtn.Add(temp);
                        if (curLen == intext.Length)
                            isfit = false;
                        else
                            intext = intext.Substring(curLen);
                        bFlag = cFlag = 0;
                        curLen = testLen;
                    }
                    else
                    {
                        bFlag = cFlag;
                        if (cFlag > 0)//太长
                            curLen--;
                        else//太短
                            curLen++;
                    }
                }
            }
            return rtn;
        }


        private void Form1_Resize(object sender, EventArgs e)
        {
            this.Invalidate();
        }

        private void Form1_ResizeEnd(object sender, EventArgs e)
        {
            Settings.Default.FormSize = this.Size;
            Settings.Default.Save();
        }


        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Space || e.KeyCode==Settings.Default.NextPage)
            {
                NextPage();
            }
        }

        private void NextPage()
        {
            startLine = endLine;
            inStartLine = inEndLine;
            this.Invalidate();
        }

        private void sToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmSettings fs = new frmSettings();
            fs.Show();
        }

        private void mnuFileExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            statTime.Text = DateTime.Now.ToString("HH:mm:ss");
        }


        private bool IsNumeric(object a)
        {
            System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"^\d+$");
            return r.IsMatch(a.ToString());
        }

        private void mnuSettingsReadOption_Click(object sender, EventArgs e)
        {
            frmSettings frm = new frmSettings();
            frm.Show(this);
        }
    }
}
